/*
 *  ckr_spec_ConsoleSpecRunner.h
 *  ckrSpec
 *
 *  Created by C. Keith Ray on 2006.11.13.
 *  Copyright 2006 __MyCompanyName__. All rights reserved.
 *
 */

#pragma once

#include "ckr_spec_SpecRunner.h"
#include "ckr_spec_SpecListener.h"
#include "ckr_spec_StringUtils.h"

#include <iosfwd>
#include <string>
#include <map>

namespace  ckr
{

//  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	const std::string kAllCmd							= "all";
	const std::string kQuickOnlyCmd					= "quick";
	const std::string kNewFirstCmd					= "new";
	const std::string kSelectedCmd					= "selected";
	const std::string kFailingCmd						= "failing";

//  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	class StdOutStreamSpecListener;
	class ConsoleSpecRunner;
	class ConsoleCommand;

	typedef std::map<std::string,ConsoleCommand*> ConsoleCommandMap;

	class ConsoleSpecRunner : public SpecRunner
	{
	public:

		static const std::string kMenuString; /* = 
									"command         [abbreviation]\n"
									"-------         ---\n"
									"run all         [ra]\n"
									"run quick       [rq]\n"
									"run new         [rn]\n"
									"run selected    [rs]\n"
									"run failing     [rf]\n"

									"list all        [la]\n"
									"list quick      [lq]\n"
									"list new        [ln]\n"
									"list selected   [ls]\n"
									"list failing    [lf]\n"

									"summary         [sum]\n"

									"quit            [q]\n"
									"exit            [ex]\n"

									"select <name>   [sel]\n"
									"select <name> - <name>\n"
									"select <name> , <name> , ...\n";

									"clear           [cl]\n"; */

		static const std::string kRunCmd;				// "run"
		static const std::string kListCmd;				// "list"

		// const std::string kAllCmd;					// "all"
		// const std::string kQuickOnlyCmd;			// "quick"
		// const std::string kNewFirstCmd;			// "new"
		// const std::string kSelectedCmd;			// "selected"
		// const std::string kListFailingCmd;		// "failing"

		static const std::string kRunAllAbbrev;				// "ra"
		static const std::string kRunQuickOnlyAbbrev;		// "rq"
		static const std::string kRunNewFirstAbbrev;			// "rn"
		static const std::string kRunFailingFirstAbbrev;	// "rf"
		static const std::string kRunSelectedAbbrev;			// "rs"

		static const std::string kListAllAbbrev;				// "la"
		static const std::string kListQuickAbbrev;			// "lq"
		static const std::string kListNewAbbrev;				// "ln"
		static const std::string kListFailingAbbrev;			// "lf"
		static const std::string kListSelectedAbbrev;		// "ls"

		static const std::string kSummaryCmd;			// "summary";
		static const std::string kSummaryAbbrev;		// "sum";

		static const std::string kQuitCmd;				// "quit";
		static const std::string kQuitAbbrev;			// "q";
		static const std::string kExitCmd;				// "exit";
		static const std::string kExitAbbrev;			// "ex";

		static const std::string kSelectCmd;			// "select";
		static const std::string kSelectAbbrev;		// "sel";

		static const std::string kClearCmd;				// "clear";
		static const std::string kClearAbbrev;			// "cl";

		static const std::string nameTitle;				// "Name"
		static const std::string resultTitle;			// "Result"
		static const std::string hasBeenRunTitle;		// "HasBeenRun"
		static const std::string durationTitle;		// "Duration"

		static const int kBetweenCols;					// 2;
		static const int resultWidth;	// = resultTitle.length() + kBetweenCols;
		static const int hasBeenRunWidth; // = hasBeenRunTitle.length() + kBetweenCols;
		static const int durationWidth; // = durationTitle.length() + kBetweenCols;



		ConsoleSpecRunner();

		ConsoleSpecRunner(const SpecRunner& rhs);

		virtual ~ConsoleSpecRunner();



		virtual void outputMenu( std::ostream& outStream );
		
		virtual void processInput( std::ostream& outStream, 
							std::istream& inStream );

		virtual void printSummary( std::ostream& outStream );

		virtual void printAllSpecs( std::ostream& outStream );

		virtual void printFailingSpecs( std::ostream& outStream );
		virtual void printFastSpecs( std::ostream& outStream );
		virtual void printNewSpecs( std::ostream& outStream );
		virtual void printSelectedSpecs( std::ostream& outStream );

		virtual void printSpecs( const ContextList& specs, 
							std::ostream& outStream );

		virtual int computeNameWidth( const ContextList& specs );
		
		virtual void printSpecColumnTitles( std::ostream& outStream, 
							int nameWidth );

		virtual void printSpecRow( const Context*		aContext, 
											std::ostream&		outStream, 
											int					nameWidth );

		virtual bool isQuitting() const;
		virtual void setIsQuitting( bool val );


		virtual ContextList selectedContexts() const;

		virtual void selectOneName( const std::string& contextNameIn );

		virtual void selectNameRange( const std::string& firstName,
					const std::string& secondName );

		virtual void selectNameCommaList( const StringList& strList,
					int startIndex );

		virtual void clearSelection();
		
		virtual void runSelectedOnly( SpecListener* listenerIn );

	private:
	
		ConsoleCommandMap myCommands;
		bool					myIsQuitting;
		ContextList			mySelectedContexts;
	};

//  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	class ConsoleCommand
	{
	public:
		explicit ConsoleCommand( ConsoleSpecRunner* runnerIn );
		virtual ~ConsoleCommand();
		
		virtual void execute( SpecListener* aListener, 
							const StringList&		strList,
							std::ostream&			outStream ) = 0;

	protected:
		ConsoleSpecRunner* runner;
	};

//  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

}; // namespace

